#ifndef napyr2_Object_H
#define napyr2_Object_H

// *****************************************************************************************
//
// NAPYR2 (http://p-nand-q.com/python/napyr.html)
//
// Copyright (c) 2014, Gerson Kurz
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 
// 2. Redistributions in binary form must reproduce the above copyright notice, this
//    list of conditions and the following disclaimer in the documentation and/or other
//    materials provided with the distribution.
// 
// 3. Neither the name of the copyright holder nor the names of its contributors may
//    be used to endorse or promote products derived from this software without
//    specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *****************************************************************************************

#include "napyr2.h"

#include <string>
#include <vector>
#include <map>

namespace napyr2 // begins here
{

#pragma warning( push )
#pragma warning( disable: 4251 )

class NAPYR2_API PythonObject
{
public:
	PythonObject()
		:	m_pyObject( NULL )
	{
	}

	PythonObject( PyObject* value );
	PythonObject( LPCSTR value );
	PythonObject( LPCWSTR value );
	PythonObject( const std::string& value );
	PythonObject( int value );
	PythonObject( unsigned int value );
	PythonObject( long value );
	PythonObject( unsigned long value );
	PythonObject( long long value );
	PythonObject( unsigned long long value );
	PythonObject( double value );
	PythonObject( unsigned char* pBytes, unsigned long ulSize );
	virtual ~PythonObject();

public:
	PythonObject( const PythonObject& objectSrc );
	PythonObject& operator=( const PythonObject& objectSrc );

public:
	static PythonObject None;
	static PythonObject True;
	static PythonObject False;

public:
	template <typename T> bool Get(T& value) const
	{
		return GetFromObject(m_pyObject, value);
	}

	template <typename T> bool GetAt( int index, std::string& value ) const
	{
		if( !m_pyObject )
			return false;

		if( PyTuple_Check(m_pyObject) )
		{
			if( (index >= 0) && (index < PyTuple_GET_SIZE(m_pyObject)) )
			{
				return GetFromObject(PyTuple_GET_ITEM(m_pyObject, index), value);
			}
		}
		else if( PyList_Check(m_pyObject) )
		{
			if( (index >= 0) && (index < PyList_GET_SIZE(m_pyObject)) )
			{
				return GetFromObject(PyList_GET_ITEM(m_pyObject, index), value);
			}
		}
		return false;
	}

	const char* repr() const;

	template <typename T> operator T() const
	{
		T result = T();
		Get(result);
		return result;
	}

private:
	void CreateFromResult( PyObject* pyResult )
	{
		m_pyObject = pyResult;
	}

private:
	friend class PythonCall;
	friend class InvokeBase;

	static bool GetFromObject( PyObject* pyObject, std::string& value );
	static bool GetFromObject( PyObject* pyObject, int& value );
	static bool GetFromObject( PyObject* pyObject, unsigned int& value );
	static bool GetFromObject( PyObject* pyObject, long& value );
	static bool GetFromObject( PyObject* pyObject, unsigned long& value );
	static bool GetFromObject( PyObject* pyObject, long long& value );
	static bool GetFromObject( PyObject* pyObject, unsigned long long& value );
	static bool GetFromObject( PyObject* pyObject, double& value );
	static bool GetFromObject( PyObject* pyObject, bool& value );

public:
	PyObject* AddRef() const;

private:
	PyObject* m_pyObject;
};

#pragma warning( pop )
} // namespace napyr2 ends here

#endif // napyr2_Object_H
